package com.ygqh.baby.service.task.impl;

import com.ygqh.baby.ao.BalanceType;
import com.ygqh.baby.ao.PromotionType;
import com.ygqh.baby.ao.TaskMethod;
import com.ygqh.baby.ao.YgQuartzJob;
import com.ygqh.baby.handler.DefaultPromotionTagHandler;
import com.ygqh.baby.model.BalanceDiff;
import com.ygqh.baby.model.CheckStockModel;
import com.ygqh.baby.model.MonitorError;
import com.ygqh.baby.model.MonitorResult;
import com.ygqh.baby.po.*;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.task.YgMonitoringService;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.MailUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
public class YgMonitoringImpl implements YgMonitoringService {
    protected final Logger logger = Logger.getLogger(this.getClass());

    @Autowired
    private YgTaskTimeService ygTaskTimeService;
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private YgOrderService ygOrderService;
    @Autowired
    private YgStockService ygStockService;
    @Autowired
    private YgUserBalanceService ygUserBalanceService;
    @Autowired
    private YgMobileService ygMobileService;
    @Autowired
    private YgLogisticsService ygLogisticsService;
    @Autowired
    private ScheduleJobService scheduleJobService;
    @Autowired
    private YgProductPackV2Service ygProductPackV2Service;
    @Autowired
    private MailUtil mailUtil;
    @Value("${mail.to.js}")
    protected String toJS;
    @Value("${mail.to.kefu}")
    protected String kefu;
    @Value("${mail.to.yy}")
    protected String yuying;
    @Value("${mail.to.yushou}")
    protected String yushou;

    private static TaskMethod[] taskArr = new TaskMethod[]{TaskMethod.PreBalanceTask, TaskMethod.AffiliateUserReportV2, TaskMethod.SyncLogistics,
            TaskMethod.SyncStockIn, TaskMethod.SyncStockOut, TaskMethod.SyncWDTOrder, TaskMethod.ChannelScan, TaskMethod.CalculateAddedUsers,
            TaskMethod.ReturnOrderForCompleteTask, TaskMethod.ReturnOrderForCancelTask,TaskMethod.StatisticsOrderByMinute,
            TaskMethod.GroupOrderIncompleteReminder, TaskMethod.GroupOrderComplete, TaskMethod.MonitorPushOrderToWDT, TaskMethod.OrderStatusForSuccessTask};

    @Override
    public void monitoringSystem() {
        Date currentTime = new Date();
        List<MonitorResult> results = new ArrayList<MonitorResult>();
        MonitorResult jobs = this.monitoringScheduledJobs(null, currentTime);
        MonitorResult sms = this.monitoringSMS(currentTime);
        MonitorResult balance = this.monitoringBalance(currentTime);
        MonitorResult order = this.monitoringOrder(currentTime);
        MonitorResult stock = this.monitoringStock(currentTime);
        MonitorResult user = this.monitoringUser(currentTime);
        results.add(jobs);
        results.add(sms);
        results.add(balance);
        results.add(stock);
        results.add(user);
        results.add(order);

        this.sendMallAndSms(results, false);
        ygTaskTimeService.saveOrUpdate("monitoringSystem", currentTime, "执行成功");
    }

    @Override
    public MonitorResult monitoringScheduledJobs(TaskMethod[] tasks, Date currentTime) {
        List<YgTaskTime> taskMothd = ygTaskTimeService.find();
        if (tasks == null || tasks.length == 0) {
            tasks = taskArr;
        }
        List<TaskMethod> taskList = Arrays.asList(tasks);
        List<MonitorError> errors = new ArrayList<MonitorError>();
        for (YgTaskTime task : taskMothd) {
            if (taskList.contains(task.getTaskMehtod())) {
                TaskMethod method = task.getTaskMehtod();
                if (method == null) {
                    continue;
                }
                Boolean hasError = false;
                long diff = 0L;
                if (method.getIntervalType().equals("day")) {
                    diff = DateConvertUtils.diffDayes(task.getRunTime(), currentTime);
                } else {
                    diff = DateConvertUtils.diffMinutes(task.getRunTime(), currentTime);
                }
                if (diff > method.getCode().longValue()) {
                    // 有异常
                    hasError = true;
                }
                if (hasError) {
                    MonitorError error = new MonitorError(method.getTitle(), "执行失败", task.getRunTime());
                    logger.error(error.getMessage());
                    errors.add(error);
                }
            }
        }
        MonitorResult result = null;
        if (CollectionUtils.isEmpty(errors)) {
            result = new MonitorResult(1, "", errors);
        } else {
            result = new MonitorResult(-1, "", errors);
        }
        return result;

    }

    @Override
    public MonitorResult monitoringUser(Date currentTime) {
        long limit = 12 * 60 * 60 * 1000;
        YgUser lastUser = ygUserService.findLastUser();
        List<MonitorError> errors = null;
        if (lastUser.getCreateTime().before(currentTime)) {
            long diff = currentTime.getTime() - lastUser.getCreateTime().getTime();
            // 是否超过12个小时没有新增用户
            if (diff / limit > 0) {
                errors = new ArrayList<>();
                MonitorError error = new MonitorError("监控用户新增", "已经超过" + diff / limit + "个小时未新增用户", lastUser.getCreateTime());
                logger.error(error.getMessage());
                errors.add(error);
            }

        }
        if (errors != null) {
            return new MonitorResult(-1, "", errors);
        }
        return new MonitorResult(1, "", errors);
    }

    @Override
    public MonitorResult monitoringOrder(Date currentTime) {
        long limit = 1 * 60 * 60 * 1000;
        List<MonitorError> errors = null;
        YgOrder lastOrder = ygOrderService.findLastOrder(null, true);
        if (lastOrder.getPaidTime().before(currentTime)) {
            long diff = currentTime.getTime() - lastOrder.getPaidTime().getTime();
            // 是否超过1个小时没有支付订单
            if (diff / limit > 0) {
                errors = new ArrayList<MonitorError>();
                MonitorError error = new MonitorError("监控订单支付", "已经超过" + diff / limit + "个小时未有支付订单", lastOrder.getPaidTime());
                errors.add(error);
            }
        }

        if (errors != null) {
            return new MonitorResult(-1, "", errors);
        }
        return new MonitorResult(1, "", errors);
    }

    @Override
    public MonitorResult monitoringSMS(Date currentTime) {
        Date start = DateConvertUtils.addMinute(currentTime, -60);
        List<MonitorError> errors = null;
        int count = ygMobileService.countByTime(start, currentTime);
        if (count > 500) {
            errors = new ArrayList<MonitorError>();
            MonitorError error = new MonitorError("监控短信",
                    DateConvertUtils.formatDateTime(start) + "至" + DateConvertUtils.formatDateTime(currentTime) + "发送短信" + count + "条", currentTime);
            errors.add(error);
            logger.error(error.getMessage());
        }
        if (errors != null) {
            return new MonitorResult(-1, "", errors);
        }
        return new MonitorResult(1, "", errors);
    }

    @Override
    public MonitorResult monitoringStock(Date currentTime) {
        long limit = 1 * 60 * 60 * 1000;
        List<MonitorError> errors = null;
        YgStock lastUpdate = ygStockService.findLastUpdate("sync");
        if (lastUpdate.getUpdateTime().before(currentTime)) {

            long diff = currentTime.getTime() - lastUpdate.getUpdateTime().getTime();
            if (diff / limit > 0) {
                errors = new ArrayList<MonitorError>();
                MonitorError error = new MonitorError("监控库存同步", "已经超过" + diff / limit + "个小时未同步库存", lastUpdate.getUpdateTime());
                errors.add(error);
            }
        }
        if (errors != null) {
            return new MonitorResult(-1, "", errors);
        }
        return new MonitorResult(1, "", errors);
    }

    @Override
    public MonitorResult monitoringBalance(Date currentDate) {
        List<BalanceDiff> diffs = ygUserBalanceService.findDifference(BalanceType.Balance);
        List<MonitorError> errors = null;
        if (!CollectionUtils.isEmpty(diffs)) {
            errors = new ArrayList<MonitorError>();
            for (BalanceDiff diff : diffs) {
                MonitorError error = new MonitorError("监控返利差异", "用户id为：" + diff.getUserId() + "，platformNo: + " + diff.getPlatformNo() + "的用户返利存在差异;", currentDate);
                errors.add(error);
            }
            return new MonitorResult(-1, "", errors);
        }
        return new MonitorResult(1, "", errors);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void sendMallAndSms(List<MonitorResult> results, Boolean sendSms) {
        List<MonitorError> errors = new ArrayList<MonitorError>();
        if (!CollectionUtils.isEmpty(results)) {
            for (MonitorResult result : results) {
                if (result.getCode() != 1) {
                    errors.addAll((Collection<? extends MonitorError>) result.getExtras());
                }
            }
        }
        if (!CollectionUtils.isEmpty(errors)) {

            StringBuffer str = new StringBuffer();
            str.append(
                    "<html><head><style>.table-d table{ background:#000;font-size:14px} .table-d table td{ background:#FFF} h5{width: auto;margin-right: 20px} .title{display: flex;line-height: 10px}");
            str.append("</style></head><body>");
            // str.append("<div><h5>合同编号：" + "" + "</h5></div>");
            str.append("<div class='table-d'>");
            str.append("<table width='800' border='0' cellspacing='1' cellpadding='0'><tr><td width='15%'>监控内容</td>" + "<td width='15%'>报警内容</td></tr>");
            for (MonitorError error : errors) {

                str.append("<tr><td>" + error.getMethod() + "</td>");
                str.append("<td>" + error.getMessage() + "</td></tr>");
            }
            str.append("</table>");
            try {
                System.out.println(str.toString());
                Calendar c = Calendar.getInstance();
                int hour = c.get(Calendar.HOUR_OF_DAY);
                if (hour > 8) {
                    mailUtil.sendWithHtml(toJS.split(","), "系统监控服务", str.toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void sendMallWithOrderExpress(Long userId, String to) {
        ygTaskTimeService.execute(TaskMethod.SendMallWithOrderExpress, 1, new YgTaskTimeTemplate() {

            @Override
            public void execute(Date date) throws Exception {
                Date startDate = DateConvertUtils.addDay(date, -1);

                List<YgLogistics> list = ygLogisticsService.findLogistics(userId, startDate, date);

                if (!CollectionUtils.isEmpty(list)) {

                    StringBuffer str = new StringBuffer();
                    str.append(
                            "<html><head><style>.table-d table{ background:#000;font-size:14px} .table-d table td{ background:#FFF} h5{width: auto;margin-right: 20px} .title{display: flex;line-height: 10px}");
                    str.append("</style></head><body>");
                    // str.append("<div><h5>合同编号：" + "" + "</h5></div>");
                    str.append("<div class='table-d'>");
                    str.append("<table width='800' border='0' cellspacing='1' cellpadding='0'><tr><td width='15%'>订单号</td>" + "<td width='15%'>收货人</td>"
                            + "<td width='15%'>收货地址</td>" + "<td width='15%'>物流公司</td>" + "<td width='15%'>快递单号</td>" + "<td width='15%'>发货时间</td></tr>");
                    for (YgLogistics l : list) {

                        str.append("<tr><td>" + l.getOrderId() + "</td>");
                        str.append(" <td>" + l.getReceiver() + "</td>");
                        str.append(" <td>" + l.getAddr() + "</td>");
                        str.append(" <td>" + l.getExpressCompany() + "</td>");
                        str.append(" <td>" + l.getExpressCode() + "</td>");
                        str.append("<td>" + DateConvertUtils.formatDateTime(l.getSendTime()) + "</td></tr>");
                    }
                    str.append("</table>");
                    System.out.println(str.toString());
                    try {
                        mailUtil.sendWithHtml(to.split(","), DateConvertUtils.format(startDate) + "年糕妈妈订单物流信息", str.toString());
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw e;
                    }

                }
                // ygTaskTimeService.saveOrUpdate(TaskMethod.SendMallWithOrderExpress.name(),
                // date, list.size() + "");
            }
        });

    }

    @Override
    public void checkStock() {

        List<CheckStockModel> list = ygStockService.checkStock();
        if (!CollectionUtils.isEmpty(list)) {

            StringBuffer str = new StringBuffer();
            if (list.size() > 0) {
                str.append(
                        "<html><head><style>.table-d table{ background:#000;font-size:14px} .table-d table td{ background:#FFF} h5{width: auto;margin-right: 20px} .title{display: flex;line-height: 10px}");
                str.append("</style></head><body>");
                str.append("<div class='title'><h5>库存报告</h5>");
                str.append("</div><div class='table-d'>");
                str.append(
                        "<table width='800' border='0' cellspacing='1' cellpadding='0'><tr><td width='5%'>序号</td><td width='15%'>商品名称</td><td width='15%'>sku编号</td><td width='15%'>尺码</td><td width='15%'>M站库存</td><td width='15%'>更新时间</td></tr>");

                for (int i = 0; i < list.size(); i++) {
                    CheckStockModel s = list.get(i);
                    str.append("<tr><td>" + (i + 1) + "</td>");
                    str.append("<td>" + s.getProductName() + "</td>");
                    str.append("<td>" + s.getSkuCode() + "</td>");
                    str.append("<td>" + s.getSizeName() + "</td>");
                    str.append("<td>" + s.getAmount() + "</td>");
                    // str.append("<td>" + (s.getRealAmount() != null ?
                    // s.getRealAmount() : "") + "</td>");
                    str.append("<td>" + (s.getUpdateTime() != null ? DateConvertUtils.formatDateTime(s.getUpdateTime()) : "") + "</td>");
                    str.append("</tr>");
                }
            }
            try {
                String to = yushou + ",guohao@yiigoo.com";
                mailUtil.sendWithHtml(to.split(","), "库存检查报告", str.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Autowired
    private DefaultPromotionTagHandler defaultPromotionTagHandler;

    @Override
    public void checkPromotionTags() {
        YgTaskTime lastByTaskMethod = ygTaskTimeService.findLastByTaskMethod(TaskMethod.CheckPromotionTags);
        Date startTime;
        if (lastByTaskMethod != null) {
            startTime = lastByTaskMethod.getRunTime();
        } else {
            startTime = DateConvertUtils.getDateStart(new Date());
            lastByTaskMethod = new YgTaskTime();
            lastByTaskMethod.setMothodName(TaskMethod.CheckPromotionTags.name());
        }
        Date endTime = new Date();

        StringBuilder remark = new StringBuilder();
        List<YgProductPack> productPacks = ygProductPackV2Service.findByUpdateTime(startTime, endTime);
        for (YgProductPack ygProductPack : productPacks) {
            String jobGroup = YgQuartzJob.PromotionTag.getJobGroup();
            String jobName = YgQuartzJob.PromotionTag.getJobName(PromotionType.Pack + "_" + ygProductPack.getId());
            Boolean exitJob = scheduleJobService.exitJob(jobName, jobGroup);
            if (!exitJob) {
                remark.append(jobName).append(",");
                defaultPromotionTagHandler.updatePromotionTag(ygProductPack.getId(), PromotionType.Pack, null, null
                        , true);
            }
        }
        lastByTaskMethod.setRunTime(endTime);
        lastByTaskMethod.setRemark(remark.toString());
        ygTaskTimeService.saveOrUpdate(lastByTaskMethod);
    }

}
